package com.marktim.pokerpoker.server;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import android.os.Handler;
import android.util.Log;

public class Server {

	private ServerSocket serverSocket;
	private Handler updateConversationHandler;
	private Thread serverThread = null;
	private ServerListener listener;
	public static final int SERVERPORT = 1406;

	private String name;
	private int maxPlayers;
	private int[] chipValues;
	private int[] initCount;
	private int smallBlind;
	private int bigBlind;
	private boolean increaseBlinds;

	private List<Socket> clients;

	public Server(String name, int max, int[] values, int[] count, int small, int big, boolean increase) {
		this.name = name;
		this.maxPlayers = max;
		this.chipValues = values;
		this.initCount = count;
		this.smallBlind = small;
		this.bigBlind = big;
		this.increaseBlinds = increase;

		clients = new ArrayList<Socket>();
		updateConversationHandler = new Handler();

		this.serverThread = new Thread(new ServerThread());
		this.serverThread.start();
	}

	public void stop() {
		try {
			serverSocket.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void setListener(ServerListener l) {
		listener = l;
	}

	public void sendToClient(Socket client, String content) {
		try {
			PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())), true);
			out.println(content);
			Log.d("SERVER", "Sent " + content + " to client " + client.getInetAddress().getHostAddress());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public void sendToAllClients(String content) {
		for (Socket s: clients) {
			sendToClient(s, content);
		}
	}

	class CommunicationThread implements Runnable {

		private Socket clientSocket;

		private BufferedReader input;

		public CommunicationThread(Socket clientSocket) {
			this.clientSocket = clientSocket;
			try {
				this.input = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		public void run() {
			while (!Thread.currentThread().isInterrupted()) {
				try {
					String read = input.readLine();
					updateConversationHandler.post(new UpdateUIThread(clientSocket.getInetAddress().getHostAddress() + ": "+ read));

					sendToAllClients(clientSocket.getInetAddress().getHostAddress() + ": " + read);
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	class ServerThread implements Runnable {

		public void run() {
			Socket socket = null;
			try {
				//create server
				serverSocket = new ServerSocket(SERVERPORT);

				//Print own IP on screen
				Enumeration<NetworkInterface> n = NetworkInterface.getNetworkInterfaces();
				while (n.hasMoreElements()) {
					NetworkInterface e = n.nextElement();
					System.out.println("Interface: " + e.getName());
					Enumeration<InetAddress> a = e.getInetAddresses();
					while (a.hasMoreElements()) {
						InetAddress addr = a.nextElement();
						if (addr.getHostAddress().startsWith("192")) {
							listener.onMessage("IP: " + addr.getHostAddress() + "\n\n");
							break;
						}
					}
				}

			} catch (IOException e) {
				e.printStackTrace();
			}
			while (!Thread.currentThread().isInterrupted()) {

				try {

					socket = serverSocket.accept();
					clients.add(socket);

					updateConversationHandler.post(new UpdateUIThread("Client connected: " + socket.getInetAddress().getHostAddress()));

					CommunicationThread commThread = new CommunicationThread(socket);
					new Thread(commThread).start();

				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	class UpdateUIThread implements Runnable {
		private String msg;

		public UpdateUIThread(String str) {
			this.msg = str;
		}

		@Override
		public void run() {
			if (listener != null)
				listener.onMessage(msg);
		}

	}

	public interface ServerListener {
		public void onMessage(String message);
	}

}
